﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GOFconsole
{
    public class Chapter10_Template
    {
        public void TemplateTest()
        { 
            //模型方法
            AbstractClass ac;
            ac = new ConcreteClassA();
            ac.TemplateMethod();

            ac = new ConcreteClassB();
            ac.TemplateMethod();

            //DEMO
            Console.WriteLine("学生甲的考卷：");
            TestPaper stuA = new StuPaperA();   //用多态实现代码的复用
            stuA.TestQuestion1();
            stuA.TestQuestion2();
            stuA.TestQuestion3();

            Console.WriteLine("学生乙的考卷：");
            TestPaper stuB = new StuPaperB();   //用多态实现代码的复用
            stuB.TestQuestion1();
            stuB.TestQuestion2();
            stuB.TestQuestion3();

        }
    }

    #region 模型
    //抽象模板，定义并实现了一个模板方法。这个模板一般是个具体的方法，给出了一个顶级逻辑的骨架，
    //而逻辑的组成步骤在相应的抽象操作中，推迟到子类实现。
    abstract class AbstractClass    
    {
        public abstract void PrimititveOperation1();    //美[ˈprɪmɪtɪv] 原始的 原生的
        public abstract void PrimititveOperation2();

        public void TemplateMethod()
        {
            PrimititveOperation1();
            PrimititveOperation2();
            Console.WriteLine(" ");
        }
    }

    //ConcreteClass,实现父类所定义的一个或多个抽象方法。每一个AbstractClaa都可以有任意多个ConcreteClass与之对应，
    //而每一个ConcreteClass都可以给出这些抽象方法的不同实现，从而使得顶级逻辑的实现各不相同。
    class ConcreteClassA : AbstractClass
    {
        public override void PrimititveOperation1()
        {
            Console.WriteLine("具体类A方法1的实现");
        }

        public override void PrimititveOperation2()
        {
            Console.WriteLine("具体类A方法2的实现");
        }
    }
    class ConcreteClassB : AbstractClass
    {
        public override void PrimititveOperation1()
        {
            Console.WriteLine("具体类B方法1的实现");
        }

        public override void PrimititveOperation2()
        {
            Console.WriteLine("具体类B方法2的实现");
        }
    }


    #endregion

    #region DEMO(抄考卷)
    class TestPaper
    {
        public void TestQuestion1()
        {
            Console.WriteLine("第一题选:"+Answer1());
        }
        protected virtual string Answer1()
        {
            return "";
        }

        public void TestQuestion2()
        {
            Console.WriteLine("第二题选:" + Answer2());
        }
        protected virtual string Answer2()
        {
            return "";
        }

        public void TestQuestion3()
        {
            Console.WriteLine("第三题选:" + Answer3());
        }
        //用了继承，并且肯定这个继承有意义，就应该要成为子类的模板，所有的重复代码都应该上升到父类去，而不是让每个子类都重复
        //如果是在超类中只提炼了题目，在子类中用base.TestQuestion()去调用并填写答案，就会有大量的base.TestQuestion()重复
        //所以用一个虚方法提供答案，目的就是给继承的之类重写，因为每个人的答案都是不同的
        protected virtual string Answer3()
        {
            return "";
        }
    }
    
    class StuPaperA : TestPaper
    {
        protected override string Answer1()
        {
            return "c";
        }
        protected override string Answer2()
        {
            return "c";
        }
        protected override string Answer3()
        {
            return "c";
        }
    }

    class StuPaperB : TestPaper
    {
        protected override string Answer1()
        {
            return "a";
        }
        protected override string Answer2()
        {
            return "a";
        }
        protected override string Answer3()
        {
            return "a";
        }
    }
    

    #endregion 

}
